package com.my.log.config;

import com.alibaba.fastjson.JSON;
import com.my.event.publisher.ApiLogPublisher;
import com.my.h2.logs.LogApi;
import com.my.log.config.annotation.ApiLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @author timo 2021/2/25
 */
@Aspect
public class ApiLogAspect {
    private static final Logger log = LoggerFactory.getLogger(ApiLogAspect.class);

    public ApiLogAspect() {
    }

    @Around("@annotation(apiLog)")
    public Object around(ProceedingJoinPoint point, ApiLog apiLog) throws Throwable {
      // 获取请求上下文
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        // 获取请求信息
        String requestUrl = request.getRequestURL().toString();
        String method = request.getMethod();
        String remoteAddr = request.getRemoteAddr();

        // 获取请求参数
        StringBuilder params = new StringBuilder();
        Enumeration<String> parameterNames = request.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String paramName = parameterNames.nextElement();
            params.append(paramName).append("=")
                  .append(request.getParameter(paramName)).append("&");
        }

        String className = point.getTarget().getClass().getName();
        String methodName = point.getSignature().getName();
        long beginTime = System.currentTimeMillis();
        Object result = point.proceed(); // 执行目标方法
        long time = System.currentTimeMillis() - beginTime;

        // 获取请求头
        Map<String, String> requestHeaders = new HashMap<>();
        Enumeration<String> reqHeaderNames = request.getHeaderNames();
        while (reqHeaderNames.hasMoreElements()) {
            String headerName = reqHeaderNames.nextElement();
            requestHeaders.put(headerName, request.getHeader(headerName));
        }
        // 获取响应头
        Map<String, String> responseHeaders = new HashMap<>();
        if (response != null) {
            Collection<String> respHeaderNames = response.getHeaderNames();
            for (String headerName : respHeaderNames) {
                responseHeaders.put(headerName, response.getHeader(headerName));
            }
        }

        // 日志输出请求头和响应头
        log.debug("请求头: {}", requestHeaders);
        log.debug("响应头: {}", responseHeaders);
        // 输出日志信息
        log.debug("请求URL: {}", requestUrl);
        log.debug("请求方法: {}", method);
        log.debug("客户端IP: {}", remoteAddr);
        log.debug("请求参数: {}", params.length() > 0 ? params.substring(0, params.length() - 1) : "");
        log.debug("响应结果: {}", result);

        LogApi logApi = new LogApi();
        logApi.setTitle(apiLog.value());
        logApi.setParams(params.length() > 0 ? params.substring(0, params.length() - 1) : "");
        logApi.setResult(JSON.toJSONString(result));
        logApi.setRequestHeaders(JSON.toJSONString(requestHeaders));
        logApi.setResponseHeaders(JSON.toJSONString(responseHeaders));
        logApi.setRequestUrl(requestUrl);
        logApi.setCreateTime(new Date());

        ApiLogPublisher.publishEvent(methodName, className, logApi, time);
        return result;
    }
}
